package com.hnucm.c201901020121.Utils.OtherUtils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.drawee.view.SimpleDraweeView;
import com.hnucm.c201901020121.R;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

//TODO 根据自己引用的RecyclerView修改引用

/**
 * Created by weixing on 2017/6/30.
 */
public class RecyclerBanner extends FrameLayout {
    /**导航圆点类型*/
    public static final short NAV_DOT = 0;
    /**导航条类型*/
    public static final short NAV_BOTTOM_BAR = 1;
    /**导航数字类型*/
    public static final short NAV_NUMBER = 2;

    private RecyclerView mRecyclerView;
    /**导航条及点的父控件*/
    private LinearLayout mDotContainer;
    /**导航dot及bar的drawable*/
    private GradientDrawable defaultDrawable, selectedDrawable;

    /**导航类型*/
    private int mNavType = 0;
    /**导航条宽度*/
    private int mNavBarWidth;
    /**导航文本控件*/
    private TextView mNavNumber;
    /**导航控件底部边距*/
    private int navBottomMargin = 30;

    /**默认导航颜色及选中导航颜色*/
    private int defaultColor = 0x75ffffff, selectColor = 0xffFF6822;


    private RecyclerAdapter mAdapter;
    private OnPagerClickListener mPageClickListener;
    private List<BannerEntity> mData = new ArrayList<>();

    /**圆点大小*/
    private int mDotSize;
    /**手指触屏位置*/
    private int startX, startY;
    /**当前滚动位置*/
    private int currentIndex;
    /**是否滚动*/
    private boolean isPlaying;

    public interface OnPagerClickListener {

        void onClick(BannerEntity entity);
    }

    public static interface BannerEntity {
        String getUrl();
    }

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            currentIndex = currentIndex >= mData.size() - 1 ? 1 : ++currentIndex;
            if (currentIndex >= mData.size()) {
                currentIndex = currentIndex % mData.size();
            }

            mRecyclerView.smoothScrollToPosition(currentIndex);

            sendEmptyMessageDelayed(0, 3000);

        }
    };

    public RecyclerBanner(Context context) {
        this(context, null);
    }

    public RecyclerBanner(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecyclerBanner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
//        defaultDrawable = new GradientDrawable();
//        defaultDrawable.setSize(mDotSize, mDotSize);
//        defaultDrawable.setCornerRadius(mDotSize);
//        defaultDrawable.setColor(0xffffffff);
//        selectedDrawable = new GradientDrawable();
//        selectedDrawable.setSize(mDotSize, mDotSize);
//        selectedDrawable.setCornerRadius(mDotSize);
//        selectedDrawable.setColor(0xff0094ff);



        LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mDotContainer = new LinearLayout(context);
        mDotContainer.setOrientation(LinearLayout.HORIZONTAL);
        LayoutParams linearLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        mDotContainer.setGravity(Gravity.CENTER);
        linearLayoutParams.setMargins(0, 0, 0, navBottomMargin);
        mDotContainer.setPadding(mDotSize * 2, mDotSize * 2, mDotSize * 2, mDotSize * 2);
        linearLayoutParams.gravity = Gravity.BOTTOM;

        mRecyclerView = new RecyclerView(context);
        new PagerSnapHelper().attachToRecyclerView(mRecyclerView);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        mAdapter = new RecyclerAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NotNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);


                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    if (touched) {
                        int first = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
                        int last = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition();
                        int current;
                        if (first == 0) {
                            current = (int) Math.round((first + last) / 2.0 - 0.1);
                        } else {
                            current = (int) Math.round((first + last) / 2.0);
                        }

                        if (current == (mData.size() - 1)) {
                            current = 1;
                            mRecyclerView.scrollToPosition(1);
                        } else if (current == 0) {
                            current = mData.size() - 2;
                            mRecyclerView.scrollToPosition(mData.size() - 2);
                        }

                        if (currentIndex != current) {
                            currentIndex = current;
                            changePoint();
                        }

                        touched = false;
                        return;
                    }

                    if (currentIndex == mData.size() - 1) {
                        mRecyclerView.scrollToPosition(1);
                        currentIndex = 1;
                    }
                    changePoint();
                }
            }
        });

        addView(mRecyclerView, vpLayoutParams);
        addView(mDotContainer, linearLayoutParams);


        mNavBarWidth = (getResources().getDisplayMetrics().widthPixels - 160) / (mData.size() == 0 ? 5 : mData.size());
        mDotSize = (int) (6 * context.getResources().getDisplayMetrics().density + 0.5f);
        setNavColor(defaultColor, selectColor);
        initNavView();
        /*
        TODO 为方便使用没有在属性xml文件中定义属性，如果要使用则直接调用类方法设置比例
        //初始化比例
        TypedArray a = getContext().obtainStyledAttributes(attrs,
                R.styleable.RatioImageView);
        mIsWidthFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_width_fix_drawable_size_ratio,
                mIsWidthFitDrawableSizeRatio);
        mIsHeightFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_height_fix_drawable_size_ratio,
                mIsHeightFitDrawableSizeRatio);
        mHeightRatio = a.getFloat(
                R.styleable.RatioImageView_height_to_width_ratio, mHeightRatio);
        mWidthRatio = a.getFloat(
                R.styleable.RatioImageView_width_to_height_ratio, mWidthRatio);
        a.recycle();*/
    }

    public void setOnPagerClickListener(OnPagerClickListener onPagerClickListener) {
        this.mPageClickListener = onPagerClickListener;
    }

    /**设置是否应该滚动*/
    public synchronized void setPlaying(boolean playing) {
        if (!isPlaying && playing && mAdapter != null && mAdapter.getItemCount() > 2) {
            mHandler.removeMessages(0);
            mHandler.sendEmptyMessageDelayed(0, 3000);
            isPlaying = true;
        } else if (isPlaying && !playing) {
            mHandler.removeMessages(0);
            isPlaying = false;
        }
    }

    /**
     * 设置data需在setColor及setNavType之后
     * @param datas 数据列表
     * @return 数据数量
     */
    public int setDatas(List<? extends BannerEntity> datas) {
        setPlaying(false);
        mDotContainer.removeAllViews();
        if (mData != null) {
            this.mData.clear();
        } else {
            this.mData = new ArrayList<>();
        }
        this.mData.addAll(datas);

        if (this.mData.size() > 1) {
            currentIndex = 1;//设置无限循环播放
            mAdapter.notifyDataSetChanged();
            mRecyclerView.scrollToPosition(currentIndex);
//            for (int i = 0; i < this.mData.size(); i++) {
//                ImageView img = new ImageView(getContext());
//                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//                lp.leftMargin = mDotSize / 2;
//                lp.rightMargin = mDotSize / 2;
//                img.setImageDrawable(i == 0 ? selectedDrawable : defaultDrawable);
//                mDotContainer.addView(img, lp);
//            }

            if (mNavType != NAV_NUMBER) {
                for (int i = 0; i < this.mData.size(); i++) {
                    ImageView img = new ImageView(getContext());
                    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                    lp.leftMargin = mDotSize / 2;
                    lp.rightMargin = mDotSize / 2;
                    img.setImageDrawable(i == 0 ? selectedDrawable : defaultDrawable);
                    mDotContainer.addView(img, lp);
                }
            } else {
                mNavNumber.setText(String.format(Locale.CHINA, "1/%d", datas.size()));
            }

            setPlaying(true);

            mData.add(0, mData.get(mData.size() - 1));
            mData.add(mData.get(1));
        } else {
            currentIndex = 0;
            mAdapter.notifyDataSetChanged();
        }
        return this.mData.size();
    }

    private void initNavView() {
        initNavView(mNavType);
    }

    /**初始化导航类型*/
    private void initNavView(int type){
        if (type == NAV_DOT) {
            if (mDotContainer != null) {
                mDotContainer.setVisibility(VISIBLE);
            }
            if (mNavNumber != null && mNavNumber.getVisibility() == VISIBLE) {
                mNavNumber.setVisibility(GONE);
            }
            defaultDrawable = new GradientDrawable();
            defaultDrawable.setSize(mDotSize, mDotSize);
            defaultDrawable.setCornerRadius(mDotSize);
            defaultDrawable.setColor(defaultColor);
            selectedDrawable = new GradientDrawable();
            selectedDrawable.setSize(mDotSize, mDotSize);
            selectedDrawable.setCornerRadius(mDotSize);
            selectedDrawable.setColor(selectColor);
        } else if (type == NAV_BOTTOM_BAR) {
            if (mDotContainer != null) {
                mDotContainer.setVisibility(VISIBLE);
            }
            if (mNavNumber != null && mNavNumber.getVisibility() == VISIBLE) {
                mNavNumber.setVisibility(GONE);
            }

            defaultDrawable = new GradientDrawable();
            defaultDrawable.setSize(mNavBarWidth, mDotSize / 3);
            defaultDrawable.setCornerRadius(0);
            defaultDrawable.setColor(defaultColor);
            selectedDrawable = new GradientDrawable();
            selectedDrawable.setSize(mNavBarWidth, mDotSize / 3);
            selectedDrawable.setCornerRadius(0);
            selectedDrawable.setColor(selectColor);
        } else if (type == NAV_NUMBER) {
            if (mDotContainer != null) {
                mDotContainer.setVisibility(GONE);
                mDotContainer.removeAllViews();
            }
            if (mNavNumber != null) {
                mNavNumber.setVisibility(VISIBLE);
                return;
            }
            mNavNumber = new TextView(getContext());
            mNavNumber.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            
            //设置背景
            int roundRadius = 20; // 8dp 圆角半径
            int fillColor = defaultColor;//内部填充颜色
            GradientDrawable gd = new GradientDrawable();//创建drawable（动态创建shape）
            gd.setColor(fillColor);
            gd.setCornerRadius(roundRadius);
            mNavNumber.setBackground(gd);
            
            
            //设置边框
//            int strokeColor = Color.parseColor("#2E3135");//边框颜色
//            int strokeWidth = 5; // 3dp 边框宽度
//            gd.setStroke(strokeWidth, strokeColor);

            mNavNumber.setGravity(Gravity.CENTER);
            mNavNumber.setPadding(15, 6, 15, 6);
            mNavNumber.setText("0/0");
            mNavNumber.setTextColor(selectColor);
            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.gravity = Gravity.END | Gravity.BOTTOM;
            params.bottomMargin = navBottomMargin;
            params.rightMargin = navBottomMargin;
            addView(mNavNumber, params);
        }
    }


    private boolean touched = false;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touched = true;
                startX = (int) ev.getX();
                startY = (int) ev.getY();
                getParent().requestDisallowInterceptTouchEvent(true);
                setPlaying(false);
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) ev.getX();
                int moveY = (int) ev.getY();
                int disX = moveX - startX;
                int disY = moveY - startY;
                getParent().requestDisallowInterceptTouchEvent(2 * Math.abs(disX) > Math.abs(disY));
                setPlaying(false);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                setPlaying(true);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        setPlaying(true);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setPlaying(false);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        if (visibility == View.GONE) {
            //页面不可见时停止轮播
            setPlaying(false);
        } else if (visibility == View.VISIBLE) {
            // 恢复可见时开始轮播
            setPlaying(true);
        }
        super.onWindowVisibilityChanged(visibility);
    }

    /**
     * height width ratio,宽高一个固定另一个不固定时才有效果
     */
    private float ratio = 0.5f;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取宽度的模式和尺寸
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        //获取高度的模式和尺寸
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);


        //宽确定，高不确定
        if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY && ratio != 0) {
            heightSize = (int) (widthSize * ratio + 0.5f);//根据宽度和比例计算高度
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
        } else if (widthMode != MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY & ratio != 0) {
            widthSize = (int) (heightSize / ratio + 0.5f);
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
        }

        //必须调用下面的两个方法之一完成onMeasure方法的重写，否则会报错
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void setRatio(float ratio) {
        this.ratio = ratio;
    }

    /**
     * 设置导航点、条、数字颜色，数字颜色不用加selectColor
     * @param defaultColor unSelectColor
     * @param selectColor selectedColor
     */
    public void setNavColor(int defaultColor, int selectColor){
        this.defaultColor = defaultColor;
        this.selectColor = selectColor;
        if (mNavType == NAV_DOT || mNavType == NAV_BOTTOM_BAR) {
            if (defaultDrawable != null) {
                defaultDrawable.setColor(defaultColor);
            }
            if (selectedDrawable != null) {
                selectedDrawable.setColor(selectColor);
            }
        } else {
            if (mNavNumber != null) {
                mNavNumber.setTextColor(selectColor);
            }
        }

    }

    /**
     * set nav type
     * @param navType type of nav(dot bar or number)
     */
    public void setNavType(int navType) {
        if (navType != mNavType) {
            initNavView(navType);
            this.mNavType = navType;
        }
    }

    public void onDestroy() {
        setPlaying(false);
        mHandler.removeMessages(0);

        mRecyclerView.setAdapter(null);
        mRecyclerView = null;
        mData.clear();
        mData = null;
        mAdapter = null;
    }

    // 内置适配器
    private class RecyclerAdapter extends RecyclerView.Adapter implements OnClickListener {

        @NotNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            SimpleDraweeView img = new SimpleDraweeView(parent.getContext());
            RecyclerView.LayoutParams l = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            img.setScaleType(ImageView.ScaleType.CENTER_CROP);
            img.setLayoutParams(l);
            img.setId(R.id.icon);
            img.setOnClickListener(this);
            return new RecyclerView.ViewHolder(img) {
            };
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {//可自己修改使用哪种方式加载图片
//            ImageView img = (ImageView) holder.itemView.findViewById(R.id.icon);
            ((SimpleDraweeView) holder.itemView).setImageURI(mData.get(position % mData.size()).getUrl());
//            Glide.with(getContext()).load(mData.get(position % mData.size()).getUrl()).placeholder(R.mipmap.ic_launcher).error(R.drawable.arrow_left).into(img);
        }

        @Override
        public int getItemCount() {
            return mData == null ? 0 : mData.size();
        }

        @Override
        public void onClick(View v) {
            if (mPageClickListener != null) {
                mPageClickListener.onClick(mData.get(currentIndex));// TODO: 2017/7/6 返回位置或者广告链接
            }
        }
    }

    private class PagerSnapHelper extends LinearSnapHelper {

        @Override
        public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
            int targetPos = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);
            final View currentView = findSnapView(layoutManager);
            if (targetPos != RecyclerView.NO_POSITION && currentView != null) {
                int currentPostion = layoutManager.getPosition(currentView);
                int first = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
                int last = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
                currentPostion = targetPos < currentPostion ? last : (targetPos > currentPostion ? first : currentPostion);
                targetPos = targetPos < currentPostion ? currentPostion - 1 : (targetPos > currentPostion ? currentPostion + 1 : currentPostion);
            }
            return targetPos;
        }
    }

    private void changePoint() {
        if (mNavType == NAV_DOT || mNavType == NAV_BOTTOM_BAR) {
            if (mDotContainer != null && mDotContainer.getChildCount() > 0) {
                int childCount = mDotContainer.getChildCount();
                for (int i = 0; i < childCount; i++) {
                    ((ImageView) mDotContainer.getChildAt(i)).setImageDrawable(defaultDrawable);
                }
                if (currentIndex == 0) {
                    ((ImageView) mDotContainer.getChildAt(childCount - 1)).setImageDrawable(selectedDrawable);
                } else if (currentIndex == mData.size() - 1) {
                    ((ImageView) mDotContainer.getChildAt(0)).setImageDrawable(selectedDrawable);
                } else {
                    ((ImageView) mDotContainer.getChildAt(currentIndex - 1)).setImageDrawable(selectedDrawable);
                }
            }
        } else {
            mNavNumber.setText(String.format(Locale.CHINA, "%d/%d", currentIndex, mData.size() - 2));
        }
    }
}
